package com.mobilezu.mobile.pushserver.xmpp.net;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.mina.core.service.IoHandler;
import org.apache.mina.core.session.IdleStatus;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.core.session.IoSessionConfig;
import org.dom4j.io.XMPPPacketReader;
import org.jivesoftware.openfire.net.MXParser;
import org.jivesoftware.openfire.nio.XMLLightweightParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlPullParserFactory;
import com.mobilezu.mobile.pushserver.xmpp.XmppServer;


public class XmppIoHandler implements IoHandler {

	private static final Log log = LogFactory.getLog(XmppIoHandler.class);
	public static final String XML_PARSER = "XML_PARSER";// XML_������
	private static final String CONNECTION = "CONNECTION";
	private static final String STANZA_HANDLER = "STANZA_HANDLER";// �ڡ�handler
	private String serverName;

	private static Map<Integer, XMPPPacketReader> parsers = new ConcurrentHashMap<Integer, XMPPPacketReader>();

	private static XmlPullParserFactory factory = null;

	static {
		try {
			factory = XmlPullParserFactory.newInstance(
					MXParser.class.getName(), null);
			factory.setNamespaceAware(true);
		} catch (XmlPullParserException e) {
			log.error("Error creating a parser factory", e);
		}
	}

	/**
	 * ������������ServerName.
	 */
	protected XmppIoHandler() {
		serverName = XmppServer.getInstance().getServerName();
	}

	/**
	 * ��һ���µ����ӱ�������ʱ���I/O�����߳��е���
	 */
	public void sessionCreated(IoSession session) throws Exception {
		// ��180��û���յ��ͻ��˵������������ر�����
		IoSessionConfig config = session.getConfig();
		config.setIdleTime(IdleStatus.BOTH_IDLE, 180);

		log.debug("sessionCreated()...");
	}

	/**
	 * ��һ�����ӱ��򿪵�ʱ��.
	 */
	public void sessionOpened(IoSession session) throws Exception {
		log.debug("sessionOpened()...");
		log.debug("remoteAddress=" + session.getRemoteAddress());
		// Create a new XML parser
		XMLLightweightParser parser = new XMLLightweightParser("UTF-8");
		session.setAttribute(XML_PARSER, parser);
		// Create a new connection
		Connection connection = new Connection(session);
		session.setAttribute(CONNECTION, connection);
		session.setAttribute(STANZA_HANDLER, new StanzaHandler(serverName,
				connection));
	}

	/**
	 * ��һ�����ӱ��رյ�ʱ�����
	 */
	public void sessionClosed(IoSession session) throws Exception {
		log.debug("sessionClosed()...");
		Connection connection = (Connection) session.getAttribute(CONNECTION);
		connection.close();
	}

	/**
	 * ��һ�����ӳ�Ϊ���õ�ʱ�����
	 */
	public void sessionIdle(IoSession session, IdleStatus status)
			throws Exception {
		log.debug("sessionIdle()...");
		Connection connection = (Connection) session.getAttribute(CONNECTION);
		if (log.isDebugEnabled()) {
			log.debug("Closing connection that has been idle: " + connection);
		}
		connection.close();
	}

	/**
	 * ���׳��κ��쳣��ʱ�����
	 */
	public void exceptionCaught(IoSession session, Throwable cause)
			throws Exception {
		log.debug("exceptionCaught()...");
		log.error(cause);
	}

	/**
	 * ���յ�һ����Ϣ��ʱ�����
	 */
	public void messageReceived(IoSession session, Object message)
			throws Exception {
		log.debug("messageReceived()...");
		log.debug("RCVD: " + message);

		// Get the stanza handler
		StanzaHandler handler = (StanzaHandler) session
				.getAttribute(STANZA_HANDLER);

		// Get the XMPP packet parser
		int hashCode = Thread.currentThread().hashCode();
		XMPPPacketReader parser = parsers.get(hashCode);
		if (parser == null) {
			parser = new XMPPPacketReader();
			parser.setXPPFactory(factory);
			parsers.put(hashCode, parser);
		}

		// The stanza handler processes the message
		try {
			handler.process((String) message, parser);
		} catch (Exception e) {
			log.error(
					"Closing connection due to error while processing message: "
							+ message, e);
			Connection connection = (Connection) session
					.getAttribute(CONNECTION);
			connection.close();
		}
	}

	/**
	 * ��һ����Ϣ��IoSession.write(Object)д���͵�ʱ�����
	 */
	public void messageSent(IoSession session, Object message) throws Exception {
		log.debug("messageSent()...");
	}

}